Add initial specs for IO::Buffer#1297
Conversation
e0188af to
4ce76f1
Compare
core/io/buffer/initialize_spec.rb
Outdated
| # This looks like a bug to me, these should be different memory models? | ||
| # Definitely looks like a bug, created issue: https://bugs.ruby-lang.org/issues/21672 | ||
| it "creates internal-mapped buffer if INTERNAL and MAPPED are both specified" do | ||
| @buffer = IO::Buffer.new(10, IO::Buffer::INTERNAL | IO::Buffer::MAPPED) | ||
| @buffer.should.internal? | ||
| @buffer.should.mapped? | ||
| @buffer.should_not.empty? | ||
| end |
There was a problem hiding this comment.
This is very clearly a bug, so I filed it as such. Not sure if the test needs to be here. Probably not? This does not seem like behavior that should be replicated. I will delete it for now.
c307df9 to
840258b
Compare
d80c785 to
001bdd5
Compare
| @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED) | ||
| @buffer.external?.should be_false | ||
| end | ||
| end |
There was a problem hiding this comment.
suggestion: It seems to me that this logic is closer to the constructor methods specs (new/map/for) than to the predicates. I would keep here just a couple of examples when a predicate returns either true or false.
There was a problem hiding this comment.
I see what you mean, but not sure what to even leave here then, especially when many cases of these flags are not intuituve. Hmm, maybe leave these specs as-is for now, but then simplify them when we have specs for all constructors?
There was a problem hiding this comment.
As I mentioned above as for me it makes sense to have there a test case when a predicate returns true and a test case with false.
Yeah, it's OK to not make changes in this PR if you are going to add specs for constructors in a separate one.
| end | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end |
There was a problem hiding this comment.
minor: seems it's duplicated in specs for #locked?.
There was a problem hiding this comment.
This and other dupes: I thought it would be better to over-spec than to select which file these interactions shoud be in 😅 I guess it would make sense to remove them from #locked, as it's really a property of individual methods (like this https://github.com/ruby/ruby/blob/master/io_buffer.c#L1485)?
There was a problem hiding this comment.
Yeah, excessive tests shouldn't be a problem. Yes, I agree that this specs would be better to put only here.
The main criterion as for me is to look from the user point of view - where a Ruby developer would look for these specs if he wants to checks the logic.
| slice.null?.should be_false | ||
| slice.valid?.should be_false | ||
| -> { slice.get_string }.should raise_error(IO::Buffer::InvalidatedError, "Buffer has been invalidated!") | ||
| end |
There was a problem hiding this comment.
minor: seems is duplicated in specs for #valid?
There was a problem hiding this comment.
Couldn't really remove duplication, but cut off excess lines in this one and the one above.
| @buffer.locked do | ||
| -> { @buffer.resize(10) }.should raise_error(IO::Buffer::LockedError, "Cannot resize locked buffer!") | ||
| end | ||
| end |
001bdd5 to
9e6959a
Compare
|
Thank you! |
| platform_is_not :windows do | ||
| it "is true when slice is still inside the buffer" do | ||
| @buffer = IO::Buffer.new(4) | ||
| slice = @buffer.slice(1, 2) | ||
| @buffer.resize(3) | ||
| slice.valid?.should be_true | ||
| end | ||
| end |
There was a problem hiding this comment.
realloc is not guaranteed to return the same address when shrinking.
There was a problem hiding this comment.
Right, could you either fix or quarantine! do that spec?
This class currently has no specs at all. This PR adds specs for the following methods:
.new,#free,#resize,#transfer,.map,.for,.stringsand some instance methods.Special remarks:
#valid?is somewhat incomplete, as garbage-collecting a string is non-trivial (I don't know how to);#resizedoes not have tests for slices as currently it seems to be an undefined behavior, and it's not clear if it should be reproduced (yes, ruby/spec is all about reproducing even weird behavior, but bugs are a gray area still).Weird things discovered so far so I don't forget:
.newallows any and all flags (https://bugs.ruby-lang.org/issues/21672)..map, for example, has very early text) (and#lockeddoesn't mention#transfer).INTERNALandEXTERNALare unclear, not being opposites (both can be false at the same time) and not even forming an exclusive tri-state withMAPPED.READONLY.#to_s(or call all predicate methods to check for all-false).#freeeven safe on a slice? (io_buffer_free seems to work fine only because no flags are copied, not actually checking "is this a slice?").#freeon the source buffer is not safe (https://bugs.ruby-lang.org/issues/21212).#lockedstate does not propagate in either direction (^).#freeing a String-backed buffer does not invalidate its slice (shouldn't slices always become invalid without a source buffer?).#resized at any point?! (Breaks the slice if size is 0, otherwise creates a new internal buffer. (Again, this is a case of "not checking for slice, and no flags are set".))SHAREDintended to be used manually or not?PRIVATEmapping neither INTERNAL or EXTERNAL?.forand.stringwith a block are supposed to nullify buffer at the end, but buffer can be#transferred outside, is this intentional? (this creates a run-away buffer, able to change the string from wherever (but not a frozen string, at least)).#resizeon a MAPPED buffer changes it to INTERNAL on macOS and Windows.